package com.hk.pinda.authority.biz.service.auth.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.hk.common.constant.CacheKey;
import com.hk.pinda.auth.server.utils.JwtTokenServerUtils;
import com.hk.pinda.auth.utils.JwtUserInfo;
import com.hk.pinda.auth.utils.Token;
import com.hk.pinda.authority.biz.service.auth.ResourceService;
import com.hk.pinda.authority.biz.service.auth.UserService;
import com.hk.pinda.authority.dto.auth.LoginDTO;
import com.hk.pinda.authority.dto.auth.ResourceQueryDTO;
import com.hk.pinda.authority.dto.auth.UserDTO;
import com.hk.pinda.authority.entity.auth.Resource;
import com.hk.pinda.authority.entity.auth.User;
import com.hk.pinda.base.BaseResult;
import com.hk.pinda.dozer.DozerUtils;
import com.hk.pinda.exception.code.ExceptionCode;
import lombok.extern.slf4j.Slf4j;
import net.oschina.j2cache.CacheChannel;
import org.apache.commons.codec.digest.DigestUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.stream.Collectors;


/**
 *
 *
 *   认证管理器 类
 *
 *
 */

@Slf4j
@Service
public class AuthManager {


    @Autowired
    private UserService userService;

    @Autowired
    private DozerUtils dozerUtils;

    @Autowired
    private JwtTokenServerUtils jwtTokenServerUtils;


    @Autowired
    private ResourceService resourceService;


    @Autowired
    private CacheChannel cacheChannel ;


    /**
     *   登录认证逻辑编写
     *
     *
     * @param account
     * @param password
     * @return
     */
    public BaseResult<LoginDTO> login(String account, String password) {

        BaseResult<User> userBaseResult = this.check(account, password);
        Boolean isError = userBaseResult.getIsError();
        if(isError){
            return BaseResult.fail("认证失败");
        }
        User user = userBaseResult.getData();
        LoginDTO loginDTO = LoginDTO.builder().build();
        UserDTO userDTO = dozerUtils.map(user, UserDTO.class);
        loginDTO.setUser(userDTO);
        // 为用户生成jwt 令牌
        JwtUserInfo jwtUserInfo = new JwtUserInfo(user.getId(), user.getAccount(), user.getName(), user.getOrgId(), user.getStationId());
        Token token = jwtTokenServerUtils.generateUserToken(jwtUserInfo, null);
        loginDTO.setToken(token);
        ResourceQueryDTO resourceQueryDTO = ResourceQueryDTO.builder().userId(user.getId()).build();
        List<Resource> resourceList = resourceService.findVisibleResource(resourceQueryDTO);
        log.info("当前用户所拥有的资源权限为：" + JSON.toJSONString(resourceList));
        if(CollectionUtils.isNotEmpty(resourceList)){
            // 将用户对应的权限（给前端使用的）进行缓存
            List<String> permissionList = resourceList.stream().map(Resource::getCode).collect(Collectors.toList());

            loginDTO.setPermissionsList(permissionList);

            // 将用户对应的权限（给后端网关使用的） 进行缓存
            List<String>  visibleResourceList = resourceList.stream().map((resource) -> {
                return resource.getMethod() + resource.getUrl();
            }).collect(Collectors.toList());
            // 缓存权限数据
            cacheChannel.set(CacheKey.USER_RESOURCE,user.getId().toString(),visibleResourceList);
        }
        // 封装返回结果
        return BaseResult.success(loginDTO);
    }

    public BaseResult<User> check(String account, String password){

        // 校验账号， 密码是否正确
        User user = userService.getOne(Wrappers.<User>lambdaQuery().eq(User::getAccount, account));

        // 将前端提交的密码进行 md5加密
        String  md5Hex = DigestUtils.md5Hex(password);

        if(user == null || !user.getPassword().equals(md5Hex)){
            return BaseResult.fail(ExceptionCode.JWT_USER_INVALID);
        }

        return BaseResult.success(user);
    }
}
